import pandas as pd
from datetime import datetime
import datetime,os
import openpyxl
import requests,json
import webbrowser


#判断授权有效时间
def 判断授权():
    # 定义开始日期和结束日期
    start_date = datetime.datetime(2024, 2, 25)
    end_date = datetime.datetime(2024, 3, 7)
    now = datetime.datetime.now()
    # 判断当前时间是否在指定日期之间
    if start_date <= now <= end_date:
        程序授权 = True
    else:
        程序授权 = False
    程序授权 = True
    return 程序授权


def 预处理(库存表=None,入库表=None):
    #去掉换行符和空格
    if 库存表.empty==False and 入库表.empty==False:
        库存表['品类'] = 库存表['品类'].str.replace('\n', '')
        库存表['名称'] = 库存表['名称'].str.replace(' ', '')
        入库表['品类'] = 入库表['品类'].str.replace('\n', '')
        入库表['名称'] = 入库表['名称'].str.replace(' ', '')
        预处理数据 = pd.merge(库存表, 入库表, on=['品类', '名称'], how='outer')
        预处理数据['当日库存'] = 预处理数据['当日库存'].fillna(0)
        预处理数据['当日入库'] = 预处理数据['当日入库'].fillna(0)

    if 库存表.empty==False and 入库表.empty==True:
        库存表['品类'] = 库存表['品类'].str.replace('\n', '')
        库存表['名称'] = 库存表['名称'].str.replace(' ', '')
        库存表.insert(3, '当日入库', 0)
        预处理数据=库存表
    if 库存表.empty==True and 入库表.empty==False:
        入库表['品类'] = 入库表['品类'].str.replace('\n', '')
        入库表['名称'] = 入库表['名称'].str.replace(' ', '')
        入库表.insert(2, '当日库存', 0)
        预处理数据=入库表

    #第一列新增索引列：时间转字符串YYYYMMDD+品类+名称
    current_time = datetime.datetime.now().strftime('%Y%m%d')
    # 在数据框中新增第一列，并赋值为当前时间字符串
    预处理数据.insert(0, '创建索引', current_time)
    预处理数据["创建索引"]=预处理数据["创建索引"]+"_"+预处理数据["品类"]+"_"+预处理数据["名称"]
    预处理数据["创建索引"]=预处理数据["创建索引"].str.replace(' ', '')
    当天日期=datetime.datetime.now().strftime('%Y-%m-%d')
    预处理数据.insert(1, '盘点日期', 当天日期)
    预处理数据.insert(5, '昨日库存', 0)
    预处理数据.insert(7, '当日消耗', 0)
    # 预处理数据.to_excel(r"./预处理.xlsx",index=False)

    return 预处理数据


def 合法性判断(df):
    # （1）判断是否有空值，终止提示哪一行哪一列有问题；
    # （2）超过5000行，终止提示不支持；
    合法校验=True
    if len(df)>5000:
        print("数据行数超过5000笔，无法上传更新")
        合法校验=False
    # 判断是否存在空值
    null_values = df.isnull()
    # 返回包含空值的行和列索引
    rows_with_null = null_values.any(axis=1)
    cols_with_null = null_values.any()
    rows_index = df.index[rows_with_null].tolist()
    cols_index = df.columns[cols_with_null].tolist()
    if len(rows_index)>0 or len(cols_index)>0:
        合法校验=False
        print("存在空值的行索引：", rows_index,"存在空值的列索引：", cols_index)
    else:
        合法校验=True
    return 合法校验



# 拆分所有的合并单元格，并赋予合并之前的值。
# 由于openpyxl并没有提供拆分并填充的方法，所以使用该方法进行完成
def unmerge_and_fill_cells(worksheet):
    all_merged_cell_ranges = list(
        worksheet.merged_cells.ranges
    )
    for merged_cell_range in all_merged_cell_ranges:
        merged_cell = merged_cell_range.start_cell
        worksheet.unmerge_cells(range_string=merged_cell_range.coord)
        for row_index, col_index in merged_cell_range.cells:
            cell = worksheet.cell(row=row_index, column=col_index)
            cell.value = merged_cell.value
# 读取原始xlsx文件，拆分并填充单元格，然后生成中间临时文件。
def 拆分单元格(filename):
    wb = openpyxl.load_workbook(filename)
    for sheet_name in wb.sheetnames:
        sheet = wb[sheet_name]
        unmerge_and_fill_cells(sheet)
    filename = filename.replace(".xlsx", "_temp.xlsx")
    wb.save(filename)
    wb.close()
    # return 库存表信息,入库表信息


def 获取登录认证():
    url= "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"
    #应用凭证里的 app id 和 app secret
    post_data = {"app_id": "cli_a55952eac7f9500b", "app_secret": "fPhj9Ju8RPEtvxOcPzDJdbWEWh12vZRQ"}
    r = requests.post(url, data=post_data)
    tat = r.json()["tenant_access_token"]
    # print("已获取登录授权")
    return tat

#将数据集转成列表，剔除表头
def 转成列表(df):
    list=df.values.tolist()
    return list
def 转成数据集(list):
    df = pd.DataFrame(list, columns=['创建索引', '盘点日期',"品类","名称","当日库存","昨日库存","当日入库","当日消耗"])
    df_cleaned = df.dropna()
    return df_cleaned


def 判断是否存在当日数据(df,日期=None):
    if 日期==None:
        check_date=datetime.datetime.now().strftime('%Y-%m-%d')
    else:
        check_date=日期
    if check_date in df['盘点日期'].values:
        return True
    else:
        return False

def 调用接口(功能,请求数据=None,个性参数=None):
    header = {
    "Content-Type": "application/json; charset=utf-8",
    "Authorization": f"Bearer {获取登录认证()}"}
    if 功能=="单元格-追加数据":
        spreadsheetToken=个性参数[0]
        url=f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheetToken}/values_append"
        请求体data={
                  "valueRange": {
                    "range": 个性参数[1],
                    "values":请求数据
                  }
                }
        r2 = requests.post(url, data=json.dumps(请求体data), headers=header)  #请求写入
        写入状态=r2.json()["msg"]
        print( f"上传云文档状态：{写入状态}")  #输出来判断写入是否成功

    elif 功能=="单元格-向单个范围写入数据":
        spreadsheetToken=个性参数[0]
        url=f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheetToken}/values"
        请求体data={
                "valueRange":{
                    "range": 个性参数[1],
                    "values": 请求数据
                    }
                }
        r2 = requests.put(url, data=json.dumps(请求体data), headers=header)  #请求写入
        写入状态=r2.json()["msg"]
        print( f"上传云文档状态：{写入状态}")  #输出来判断写入是否成功
    elif 功能=="工作表-获取工作表":
        spreadsheetToken=个性参数[0]
        url=f"https://open.feishu.cn/open-apis/sheets/v3/spreadsheets/{spreadsheetToken}/sheets/query"
        r2 = requests.get(url, headers=header)
        最大行条数=r2.json()["data"]["sheets"][0]["grid_properties"]["row_count"]
        sheet_id=r2.json()["data"]["sheets"][0]["sheet_id"]
        return  最大行条数,sheet_id
    elif 功能=="单元格-读取单个范围":
        spreadsheetToken=个性参数[0]
        range=个性参数[1]
        url=f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheetToken}/values/{range}"
        r2 = requests.get(url,  headers=header)  #请求写入
        读取状态=r2.json()["msg"]
        print( f"读取云文档状态：{读取状态}")  #输出来判断写入是否成功
        数据=r2.json()["data"]["valueRange"]["values"]
        返回数据=转成数据集(数据)
        return  返回数据
    elif 功能=="单元格-设置单元格样式":
        spreadsheetToken=个性参数[0]
        range=个性参数[1]
        url=f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheetToken}/style"
        请求体data={
  "appendStyle":{
     "range": range,
     "style":{
          "formatter":"yyyy/MM/dd"
          }
      }
}
        r2 = requests.put(url,data=json.dumps(请求体data), headers=header)  #请求写入





# 定义要遍历的目录
登记表路径="./登记表.xlsx"
# 读取Excel文件
excel_file = pd.ExcelFile(登记表路径)
# 获取Excel文件中的所有表名
sheet_names = excel_file.sheet_names
当天日期=current_time = datetime.datetime.now().strftime('%Y%m%d')

#需要配置的表格信息
spreadsheetToken="XkIas3zWxhjxm7twgyicyxCinQb"
if 判断授权():
    拆分单元格(登记表路径)
    库存表信息=pd.read_excel(登记表路径.replace(".xlsx", "_temp.xlsx"),sheet_name=0)
    入库表信息=pd.read_excel(登记表路径.replace(".xlsx", "_temp.xlsx"),sheet_name=1)
    os.remove(登记表路径.replace(".xlsx", "_temp.xlsx"))

    if 当天日期 not in sheet_names[0]:
        print(f"{sheet_names[0]}不是当天数据,不导入:库存表")
        导入库存表=False
    elif 当天日期 in sheet_names[0]:
        print(f"{sheet_names[0]}是当天数据,导入:库存表")
        if 合法性判断(库存表信息)==True:
            导入库存表=True
    if 当天日期 not in sheet_names[1]:
        print(f"{sheet_names[1]}不是当天数据,不导入:入库表")
        导入入库表=False
    elif 当天日期 in sheet_names[1]:
        print(f"{sheet_names[1]}是当天数据,导入:入库表")
        if 合法性判断(入库表信息) == True:
            导入入库表=True

    if 导入库存表==True and 导入入库表==True:
        待导入数据=预处理(库存表信息,入库表信息)
    elif 导入库存表 == True and 导入入库表 == False:
        待导入数据 = 预处理(库存表信息, pd.DataFrame())
    elif 导入库存表 == False and 导入入库表 == True:
        待导入数据 = 预处理(pd.DataFrame(), 入库表信息)
    最大行数,sheet_id=调用接口("工作表-获取工作表",请求数据=None,个性参数=[spreadsheetToken])
    # print(最大行数,sheet_id)
    当前开始索引 = "A2"
    当前结束索引 = "H" + str(最大行数 + 1)
    云文档范围 = f"{sheet_id}!{当前开始索引}:{当前结束索引}"
    # else:
    云文档数据=调用接口("单元格-读取单个范围",个性参数=[spreadsheetToken,云文档范围])
    if 判断是否存在当日数据(云文档数据)==False:
        #如果不存在当日数据，直接追加
        写入数据长度 = len(待导入数据)
        开始索引 = "A2"
        结束索引 = "H" + str(最大行数+写入数据长度)
        写入范围 = f"{sheet_id}!{开始索引}:{结束索引}"
        #增加显示昨日库存、当日消耗
        # 使用set()函数对列表进行去重
        try:
            上个日期 = sorted(list(set(云文档数据["盘点日期"].tolist())))[-1]
            for index, row in 待导入数据.iterrows():
                上个创建索引=上个日期.replace('-', '')+"_"+row["品类"].replace(' ', '')+"_"+row["名称"].replace(' ', '')
                #考虑新建品类
                try:
                    昨日库存=云文档数据[云文档数据["创建索引"]==上个创建索引]["当日库存"].iloc[-1]
                except:
                    昨日库存=0
                待导入数据.loc[index,"昨日库存"]=昨日库存
            待导入数据["当日消耗"] = 待导入数据["昨日库存"] + 待导入数据["当日入库"] - 待导入数据["当日库存"]
        except:
            #首次创建
            待导入数据["昨日库存"] =0
            待导入数据["当日消耗"]=0
        写入数据 = 转成列表(待导入数据)
        调用接口("单元格-追加数据", 请求数据=写入数据, 个性参数=[spreadsheetToken,写入范围])
        日期开始索引=开始索引.replace("A","B")
        日期结束索引=结束索引.replace("H","B")
        刷格式写入范围 = f"{sheet_id}!{日期开始索引}:{日期结束索引}"
        调用接口("单元格-设置单元格样式", 个性参数=[spreadsheetToken, 刷格式写入范围])


        print("当日首次上传云文档数据")
    else:
        云文档当日数据=云文档数据[云文档数据["盘点日期"]==datetime.datetime.now().strftime('%Y-%m-%d')]
        # 云文档当日数据.to_excel(r"C:\Users\AXZQ\PycharmProject\dataAnalysic\闲鱼项目\项目4-云文档\云文档当日数据.xlsx",index=False)
        # 待导入数据.to_excel(r"C:\Users\AXZQ\PycharmProject\dataAnalysic\闲鱼项目\项目4-云文档\待导入数据.xlsx",index=False)
        初始行索引=云文档当日数据.index[0]
        #遍历每一行记录，查询是否存在
        变更记录=0
        for index, row in 待导入数据.iterrows():
            创建索引一致记录=云文档当日数据[云文档当日数据["创建索引"]==row["创建索引"]]
            #判断是否新增记录
            if 创建索引一致记录.empty==True:
                变更记录=变更记录+1
            else:
                其他字段一致=创建索引一致记录[(创建索引一致记录["当日库存"]==row["当日库存"]) & (创建索引一致记录["当日入库"]==row["当日入库"]) ]
                if 其他字段一致.empty==False:
                    #完全一致，无需更新
                    pass
                else:
                    变更记录=变更记录+1
        if 变更记录>0:
            #重新写入数据
            写入数据长度 = len(待导入数据)
            开始索引 = "A"+str(初始行索引+2)
            结束索引 = "H" + str(初始行索引+2 + 写入数据长度)
            写入范围 = f"{sheet_id}!{开始索引}:{结束索引}"
            # 增加显示昨日库存、当日消耗
            # 使用set()函数对列表进行去重
            上个日期 = sorted(list(set(云文档数据["盘点日期"].tolist())))[-2]
            for index, row in 待导入数据.iterrows():
                上个创建索引 = 上个日期.replace('-', '') + "_" + row["品类"].replace(' ', '') + "_" + row["名称"].replace(' ', '')
                # 考虑新建品类
                # try:
                昨日库存 = 云文档数据[云文档数据["创建索引"] == 上个创建索引]["当日库存"].iloc[-1]
                待导入数据.loc[index, "昨日库存"] = 昨日库存
                待导入数据.loc[index, "当日消耗"] = 昨日库存 + row["当日入库"] - row["当日库存"]
                # except:
                #     待导入数据.loc[index, "昨日库存"]= 0
                #     待导入数据.loc[index, "当日消耗"] = 0

            写入数据 = 转成列表(待导入数据)
            调用接口("单元格-向单个范围写入数据", 请求数据=写入数据, 个性参数=[spreadsheetToken, 写入范围])
            日期开始索引 = 开始索引.replace("A", "B")
            日期结束索引 = 结束索引.replace("H", "B")
            刷格式写入范围 = f"{sheet_id}!{日期开始索引}:{日期结束索引}"
            调用接口("单元格-设置单元格样式", 个性参数=[spreadsheetToken, 刷格式写入范围])
            print(f"当日变更已上传云文档数据，变更记录为{变更记录}条")
    # 指定要打开的网页链接
    url = 'https://aqjpn1jk570.feishu.cn/wiki/SkzKwBWBmi1Fv5kosKccCZGdnRb?table=tblYOeI4av57GY7x&view=vewJzzAEFQ'

    # 使用默认浏览器打开指定网页
    webbrowser.open(url)
    print("数据已生成,结束输入y")
    while input().lower() != 'y':
        break











